package org.cainiao.io.nio.channel.file.lock;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class FileLockThreadTest {

    private static final int SIZEOF_INT = 4;
    private static final int INDEX_START = 0;
    private static final int INDEX_COUNT = 10;
    private static final int INDEX_SIZE = INDEX_COUNT * SIZEOF_INT;

    public static void main(String[] argv) throws Exception {
        if (argv.length < 2) {
            println("Usage: filename size");
            return;
        }
        URL url = FileLockThreadTest.class.getClassLoader().getResource(argv[0]);
        if (url == null) {
            throw new RuntimeException("未找到文件");
        }
        String size = argv[1];
        System.out.println(size);
        doTask(url, Integer.parseInt(size));
//        ExecutorService executorService = Executors.newCachedThreadPool();
//        executorService.execute(() -> {
//            try {
//                doTask(url, 3);
//            } catch (IOException | InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//        });
//        executorService.execute(() -> {
//            try {
//                doTask(url, 4);
//            } catch (IOException | InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//        });

        // sameThread(url);
    }

    public static void sameThread(URL url) throws IOException, InterruptedException {
        File file = new File(url.getFile());
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw")) {
            FileChannel fc = randomAccessFile.getChannel();

            println("before lock");

            FileLock lock1 = fc.lock(INDEX_START, 4, false);

            println("after lock");

            println("lock again");
            FileLock lock2 = fc.lock(INDEX_START, 2, false);
            println("after lock again");

            lock1.release();

            println("after release lock1");

            lock2.release();

            println("after release lock2");
        }
    }

    public static void doTask(URL url, int size) throws IOException, InterruptedException {
        File file = new File(url.getFile());
        try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw")) {
            FileChannel fc = randomAccessFile.getChannel();

            println("before lock");

            FileLock lock = fc.lock(INDEX_START, size, false);

            println("after lock");

            Thread.sleep(10000);

            println("after sleep");

            lock.release();

            println("after release");
        }
    }

    private static void println(String message) {
        System.out.printf("%s %s >>> ", Thread.currentThread().getName(),
            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        System.out.println(message);
    }

}
